﻿/*************************************************************************************
 * 工    具：  HK_FirstPersonCam
 * 
 * 描    述：  HK_FirstPersonCam 是一套第一人称相机管理系统，主要用于 PC 端，提供第一人称视角控制功能
 *             
 *            角色与相机控制：支持通过鼠标和键盘进行第一人称角色控制。按住鼠标右键可灵活控制角色旋转，使用 WASD 键实现角色前后左右移动，同时支持跳跃操作。
 *            相机视角调整：相机具备缩放功能，可通过鼠标滚轮进行视野缩放，并且设置了俯仰角限制，防止相机翻转。
 *            位置切换功能：运行时，可通过发送 `CMD_FPS_ChangePos` 指令并传入对应参数，实现角色位置的快速切换。
 *            触发器管理：系统支持对 `HK_FirstPersonTrigger` 进行分组管理，运行时可通过相关指令控制分组触发器的显示与隐藏。
 * 
 * 版    本：  V1.4
 * 作    者：  京产肠饭
 * 
 * 创    建：  2023/06/27  V1.0
 * 
 * 更    新：  2024/10/23  V1.1
 *            1.功能优化：通过 ActionKit.ScreenTransition 实现眨眼效果，移除Mask物体，减少不同渲染管线的适配工作
 *
 *            2025/05/19  V1.2
 *            1.功能优化：移除对 EventSystem 组件的依赖，优化代码结构
 *            2.代码优化：优化了代码结构，使代码更易读、易维护
 *            3.功能优化：新增了设置鼠标左右键控制相机的选项
 *            4.代码优化：优化对外的接口（指令及事件）
 *            5.功能新增：新增了角色触发器及其对应Event事件
 *
 *            2025/07/04  V1.3
 *            1.功能新增：支持对 HK_FirstPersonTrigger 进行分组，新增4个Command，用于控制分组Trigger的显示及禁用（隐藏）
 *            2.功能新增：新增对 TriggerType 的唯一性检验
 *            3.功能新增：新增对 PosType 的唯一性检验
 *            4.功能优化：在编辑器下新增相关组件的图标，提高易用性
 * 
 *            2025/11/20  V1.4
 *            1.功能新增：新增 CMD_FPS_FixCamera 指令，用于固定相机到指定位置及角度, 并新增 CMD_FPS_UnFixTheCamera 指令，用于取消固定相机
 * 
 * 链    接：  https://gitee.com/JingChanChangFan/hk_-unity-tools
*************************************************************************************/

using System.Collections.Generic;
using QFramework;
using UnityEngine;

namespace HKTools
{
    public interface IHK_FirstPersonCamSystem : ISystem
    {
        HK_FirstPersonCtrl FirstPerson { get; set; }
        void InitFirstPersonCam(HK_FirstPersonCtrl firstPerson);

        void InitCamPosList(HK_FirstPersonPos pos);
        void RemoveFromCamPosList(HK_FirstPersonPos pos);

        void InitCamTriggerList(HK_FirstPersonTrigger trigger);
        void RemoveFromCamTriggerList(HK_FirstPersonTrigger trigger);

        void ChangeFirstPersonPos(HK_FirstPersonPosEnum pos_TF, bool isChangeRot);
        HK_FirstPersonPosEnum CurPos { get; set; }

        void ChangeFirstPersonTrigger(HK_FirstPersonTrigger trigger);
        HK_FirstPersonTrigger CurTrigger { get; set; }

        void ShowTriggersByGroup(HK_FirstPersonTriggerGroupEnum triggerGroup);

        void HideTriggersByGroup(HK_FirstPersonTriggerGroupEnum triggerGroup);

        void ShowAllTriggers();

        void HideAllTriggers();
    }

    public class HK_FirstPersonCamSystem : AbstractSystem, IHK_FirstPersonCamSystem
    {
        public HK_FirstPersonCtrl FirstPerson { get; set; }

        public HK_FirstPersonPosEnum CurPos { get; set; }
        // Pos 列表
        List<HK_FirstPersonPos> Pos_List { get; set; }

        public HK_FirstPersonTrigger CurTrigger { get; set; }

        // Trigger 列表，使用字典按组存储
        Dictionary<HK_FirstPersonTriggerGroupEnum, List<HK_FirstPersonTrigger>> Trigger_List { get; set; }

        protected override void OnInit()
        {
            HKDebug.Log("IHK_FirstPersonCamSystem 初始化完成!", LogColor.Cyan, LogStyle.Bold);

            Pos_List = new List<HK_FirstPersonPos>();
            Trigger_List = new Dictionary<HK_FirstPersonTriggerGroupEnum, List<HK_FirstPersonTrigger>>();
        }

        public void InitFirstPersonCam(HK_FirstPersonCtrl firstPerson)
        {
            this.FirstPerson = firstPerson;
        }

        /// <summary>
        /// 初始化 CamPos 列表
        /// </summary>
        public void InitCamPosList(HK_FirstPersonPos pos)
        {
            if (!Pos_List.Contains(pos))
            {
                Pos_List.Add(pos);
            }
        }

        /// <summary>
        /// 从 CamPos 列表 移除
        /// </summary>
        public void RemoveFromCamPosList(HK_FirstPersonPos pos)
        {
            if (Pos_List.Contains(pos))
            {
                Pos_List.Remove(pos);
            }
        }

        public void InitCamTriggerList(HK_FirstPersonTrigger trigger)
        {
            if (!Trigger_List.ContainsKey(trigger.triggerGroup))
            {
                Trigger_List[trigger.triggerGroup] = new List<HK_FirstPersonTrigger>();
            }

            if (!Trigger_List[trigger.triggerGroup].Contains(trigger))
            {
                Trigger_List[trigger.triggerGroup].Add(trigger);
            }
        }

        public void RemoveFromCamTriggerList(HK_FirstPersonTrigger trigger)
        {
            if (Trigger_List.ContainsKey(trigger.triggerGroup))
            {
                if (Trigger_List[trigger.triggerGroup].Contains(trigger))
                {
                    Trigger_List[trigger.triggerGroup].Remove(trigger);
                }
            }
        }

        public void ChangeFirstPersonPos(HK_FirstPersonPosEnum posType, bool isChangeRot)
        {
            if (FirstPerson == null)
            {
                HKDebug.LogError("FirstPerson未完成初始化！");
                return;
            }

            if (CurPos == posType)
            {
                HKDebug.Log("当前已处于 " + posType.ToString() + " 的位置...");
            }
            else
            {
                HK_FirstPersonPos pos = Pos_List.Find(p => p.posType == posType);

                FirstPerson.GetComponent<CharacterController>().enabled = false;

                ActionKit.ScreenTransition
                  .FadeInOut()
                  .In(fadeIn => fadeIn.Duration(0.4f))
                  .OnInFinish(() =>
                  {
                      FirstPerson.transform.position = pos.transform.position;
                      CurPos = posType;
                      if (isChangeRot)
                      {
                          FirstPerson.ChangeRot(pos.transform);
                      }
                      else
                      {
                          FirstPerson.ResetRot();
                      }
                      FirstPerson.GetComponent<CharacterController>().enabled = true;

                      this.SendEvent(new Event_FPS_ChangePos()
                      {
                          _posType = posType
                      });
                  })
                  .Out(fadeOut => fadeOut.Duration(0.4f))
                  .StartGlobal();
            }
        }

        public void ChangeFirstPersonTrigger(HK_FirstPersonTrigger triggerType)
        {
            if (FirstPerson == null)
            {
                HKDebug.LogError("FirstPerson未完成初始化！");
                return;
            }

            if (triggerType.isOnceTrigger)
            {
                triggerType.Hide();
            }

            CurTrigger = triggerType;

            this.SendEvent(new Event_FPS_Trigger() { _triggerType = triggerType.triggerType });
        }

        // 按组显示触发器的方法
        public void ShowTriggersByGroup(HK_FirstPersonTriggerGroupEnum triggerGroup)
        {
            if (Trigger_List.ContainsKey(triggerGroup))
            {
                foreach (var trigger in Trigger_List[triggerGroup])
                {
                    trigger.Show();
                }
            }
        }

        // 按组隐藏触发器的方法
        public void HideTriggersByGroup(HK_FirstPersonTriggerGroupEnum triggerGroup)
        {
            if (Trigger_List.ContainsKey(triggerGroup))
            {
                foreach (var trigger in Trigger_List[triggerGroup])
                {
                    trigger.Hide();
                }
            }
        }

        // 显示所有触发器的方法
        public void ShowAllTriggers()
        {
            foreach (var group in Trigger_List.Values)
            {
                foreach (var trigger in group)
                {
                    trigger.Show();
                }
            }
        }

        // 隐藏所有触发器的方法
        public void HideAllTriggers()
        {
            foreach (var group in Trigger_List.Values)
            {
                foreach (var trigger in group)
                {
                    trigger.Hide();
                }
            }
        }
    }
}